home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
game
/
shoot
/
dogfight.lha
/
DogFight!
/
Sources.lha
/
DogFight!_class9.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-21
|
18KB
|
493 lines
/********************************************************************
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
##
## DogFight!_class.h
##
## Defines Fighters, Shots, Coords, and functions on these objects.
##
## V0.6 01-MAR-94
## 03-Mar-94 Moving to real data abstraction (seperating
## the .h from the .c for this file.
## 21-May-94 Converted to SAS/C
##
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
*********************************************************************/
#include "DogFight!_class9.h"
#include "sound.h"
// why are all math functions in radians?? Who thinks in radians?!?
const float rad_inc = (TWO_PI / 360.0);
const float ri135 = (TWO_PI/360) * 135.0;
const float ri225 = (TWO_PI/360) * 225.0;
const float RADS = (rad_inc* 1.5);
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
The following code was taken from
the ASwarm module of the
GarshneBlanker sourcecodes.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
BYTE sqrt_tab[256] = {
0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,15,15
};
LONG FastSQRT( LONG x )
{
LONG sr = 1L;
while( x > 255L ) {
x /= 4L;
sr *= 2L;
}
return( sr * (LONG)sqrt_tab[x] );
}
/********************************************************************
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
The COORD class handles all of our
screen positioning, and is screen
size sensitive (assuming we set the
correct variables in the DogFight!.h)
It handles inc/decrementing (movement),
wraparound, and keeps track of the
position in floating point.
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
*********************************************************************/
COORD::COORD() {
x=y=0;
fx=fy=0.0;
xinc=yinc=0.0;
}
void COORD::set_f(float a, float b) {
fx = a;
fy = b;
x=int(fx);
y=int(fy);
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Increment the coords and check for
wraparound.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void COORD::inc() {
fx += xinc;
fy += yinc;
if (fx < scrn_left) {
fx = float(scrn_left) - fx;
fx = float(scrn_right) - fx;
}
else if (fx > (float)scrn_right) {
fx -= float(scrn_right);
fx += float(scrn_left);
}
if (fy < (float)scrn_top) {
fy = float(scrn_top) - fy;
fy = float(scrn_bottom) - fy;
}
else if (fy > (float)scrn_bottom) {
fy -= float(scrn_bottom);
fy += float(scrn_top);
}
x = int(fx);
y = int(fy);
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Returns the distance between itself
and the supplied coordinate.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
int COORD::dist(COORD a) {
static int k, l;
k = a.x-x;
l = a.y-y;
return int(FastSQRT((k*k) + (l*l)));
}
/********************************************************************
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
Our SHOT class. Since Jets don't
collide, this is the only way to shoot
down enemy craft =-).
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
*********************************************************************/
void SHOT::stop() {underway = FALSE;}
SHOT::SHOT() { underway = FALSE;}
void SHOT::bang(COORD co, float d, int pla) {
if (!underway) {
dir = d;
c = co;
underway = TRUE;
dist = 0;
c.xinc = SPSin(dir) * shotspeed[game_speed];
c.yinc = SPCos(dir) * -shotspeed[game_speed];
shoot(pla);
}
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Check for collision with the supplied
coordinate. This might be better if
we can actually check to see if we're
_inside_ a Jet, but those calculations
slow the game down too much, and
checking by pixel is unreliable.
Returns TRUE if collision, and if so,
stops shot.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
BOOL SHOT::collide(COORD b) {
if (underway) {
if (b.dist(c) < 10) {
underway = FALSE;
return TRUE;
}
}
return FALSE;
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Responsible for erasing, repositioning,
and redrawing the shot, as well
as checking to see if the shot has moved
it's maximum range.
See FIGHTER::move().
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void SHOT::move(struct RastPort *rp) {
if (underway) {
erase(rp);
old_c = c;
if (dist < 280) {
dist += shotspeed[game_speed];
c.inc();
draw(rp);
}
else {
underway = FALSE;
}
}
else if (dist) {
erase(rp);
dist = 0;
}
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Draw the shot
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void SHOT::draw(struct RastPort * rp) {
SetAPen(rp, 5);
Move(rp, c.x, c.y);
Draw(rp, c.x + int(SPSin(dir)*4), c.y + int(SPCos(dir)*-4));
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Erase the shot. See FIGHTER::erase()
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void SHOT::erase(struct RastPort * rp) {
SetAPen(rp, 0);
RectFill(rp, old_c.x - 4, old_c.y - 4,
old_c.x + 4, old_c.y + 4);
}
/********************************************************************
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
The Jet class.
We have:
* 3 coordinates for double-
buffering (to remember where we _were_),
* dir for direction, in rads (bleh!)
* turnrad for rate of turn
* 2 flags (rf&lf) for remembering in
which direction we're turning
* explosions for how big and long we
explode
* color to identify the Jet
* speed for how fast the Jet is
* deadtime to keep track of how long
we have to go before we're resurected
* txt for our Jet identification number.
* alive for whether we've been shot
* in_play to tell if the Jet is being
used
* killscore for how many jets we've
shot down
* and our very own SHOT.
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
*********************************************************************/
void FIGHTER::right() {
if (!lf) rf = TRUE;
lf = FALSE;
shootable = TRUE;
}
void FIGHTER::left() {
if (!rf) lf = TRUE;
rf = FALSE;
shootable = TRUE;
}
void FIGHTER::fire() {
if (alive & shootable) {
shot.bang(c, dir, color);
shootable = TRUE;
}
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Keeps the Jet out of play for a
certain amount of time (deadtime loops),
and then starts him up again.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::resurect(int p, int perf) {
if (deadtime)
deadtime--;
else {
init(p, perf);
start(p+1);
}
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Checks to see if the Jet has collided
with the supplied SHOT.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
BOOL FIGHTER::collide(SHOT *s) {
if (alive && shootable)
if (s->collide(c)) {
alive = FALSE;
explode(color);
return TRUE;
}
return FALSE;
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Set up Jet values.
- 'a' is the player number,
- 'perf' is the Jet type option set in
the prefs window.
Player1 (a=0) starts in the upperleft
screen corner, Player2 (a=1) in the
upperright, etc.
perf=0 means the Jet is not in play,
perf=1 is a compromise Jet, etc.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::init(int a, int perf) {
lf = rf = FALSE; // moving straight
alive = TRUE; // not dead yet
explosions = 15; // each explosion lasts 15 program loops
color = a+1;
txt = &(PLT[a]); // see DogFight!4.h
deadtime = 500; // each death lasts 500 program loops
in_play=TRUE; // assume the Jet is in play...
shootable=vulnerability;
shot.stop();
switch(perf) {
case 0: // ... because we just take it out of
in_play=FALSE; // play if perf is 0
break;
case 1: // this is the compromise Jet
speed = medium[game_speed];
turnrad = 1.7 * float(rad_inc);
break;
case 2: // the fast (Speed) Jet
speed = fast[game_speed];
turnrad = 1.2 * float(rad_inc);
break;
default: // the only other option is
speed = slow[game_speed]; // the maneuverable (slow)
turnrad = 2.2 * float(rad_inc); // Jet
break;
}
switch(a) {
case 0:
c.set_f((int)scrn_left, (int)scrn_top); // put him in the upper left
dir = float(rad_inc) * 135.0; // aim him SE
break;
case 1:
c.set_f((int)scrn_right, (int)scrn_top); // upper right
dir = float(rad_inc) * 225.0; // headed SW
break;
case 2:
c.set_f((int)scrn_left, (int)scrn_bottom); // lower left
dir = float(rad_inc) * 45.0; // headed NE
break;
case 3:
c.set_f((int)scrn_right, (int)scrn_bottom); // lower right
dir = float(rad_inc) * 315.0; // headed NW
break;
default:
break;
}
c.xinc = SPSin(dir); // start 'em out slow & steady in the initial
c.yinc = -SPCos(dir); // direction.
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Responsible for erasing, calculating
the new position, and drawing the Jet
in the supplied RastPort. Assumes that
we're double buffered; IE, that we're
drawing on exactly two screens (hence
the c, old_c, and oold_c coordinates).
Also calls the explosion routines if
the Jet is in the process of dying.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::move(struct RastPort * rp) {
shot.move(rp); // let the missile move if it wants to
if (alive) { // if we're alive...
if (rf | lf) { // if we get a turn signal
if (rf) { // if the signal is right
dir = (float)dir + (float)turnrad; // turn clockwise
if (dir > float(TWO_PI)) dir = 0.0; // IE, if dir > 360°
} // we set it to 0.
else {
dir = (float)dir - (float)turnrad; // else turn counterclockwise
if (dir < 0.0) dir = float(TWO_PI); // and complete a circle
}
c.xinc = SPSin(dir) * speed; // set the incs for the new dir
c.yinc = SPCos(dir) * -speed;
}
c.inc(); // calculate the new coordinates
draw(rp); // draw the Jet.
}
else if (explosions>1) // not alive?!? still exploding?
draw_explode(rp); // then draw explosion
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Draws a fighter in the supplied
RasterPort, and plops the text in the
middle.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::draw(struct RastPort * rp) {
static float first; // So we don't have to calculate them twice
static float second; // every time.
static WORD xy[6]; // The array for the endpoints in the Jet
first = (float)dir + (float)ri135; // down right
second= (float)dir + (float)ri225; // down left
xy[0] = c.x + int( SPSin(dir) * 13.0 );
xy[1] = c.y + int( SPCos(dir) * -13.0 );
xy[2] = c.x + int( SPSin(first) * 8.0 );
xy[3] = c.y + int( SPCos(first) * -8.0 );
xy[4] = c.x + int( SPSin(second) * 8.0 );
xy[5] = c.y + int( SPCos(second) * -8.0 );
SetAPen(rp, color);
txt->FrontPen = color;
PrintIText(rp, txt, c.x-3, c.y-3);
Move(rp, xy[4], xy[5]);
PolyDraw(rp, 3, xy);
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Quick erase of the fighter shape.
It would be better to erase just the
shape instead of a block fill, but
it takes too long.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::erase(struct RastPort * rp) {
SetAPen(rp, 0);
if (alive) { // if alive, erase Jet
RectFill(rp, old_c.x - 13, old_c.y - 13,
old_c.x + 13, old_c.y + 13);
RectFill(rp, old_c.x-3, old_c.y-3, old_c.x + 8, old_c.y + 9);
old_c = c;
}
else if (explosions) { // otherwise, erase
explosions--; // explosions
RectFill(rp, c.x - (explosions + 2),
c.y - (explosions + 2),
c.x + (explosions + 2),
c.y + (explosions + 2));
}
}
/******************************************
×××××××××××××××××××××××××××××××××××××××××××
Draws a simple explosion with a
radius of 'explosions' in the supplied
RasterPort.
×××××××××××××××××××××××××××××××××××××××××××
******************************************/
void FIGHTER::draw_explode(struct RastPort * rp) {
float i;
SetAPen(rp, color);
for (i = 0; i < TWO_PI; i = (float)i + (float)(PI/5)) {
Move(rp, c.x, c.y);
Draw(rp, c.x + int(SPSin(i) * explosions),
c.y + int(SPCos(i) * explosions));
}
}